package org.zyx.item.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zyx.item.bo.SpuBo;
import org.zyx.item.entity.Sku;
import org.zyx.item.entity.Spu;
import org.zyx.item.entity.SpuDetail;
import org.zyx.item.entity.Stock;
import org.zyx.item.mapper.*;
import org.zyx.yiyou.common.entity.PageResult;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: SwordMaple
 * @Date: 2020/9/7  20:46
 * @Description: 集合Spu, SpuDetails, Sku 商品信息
 * @Version: 1.0
 */

@Service
public class GoodsService {

    @Resource
    private SpuDetailMapper spuDetailMapper;
    @Resource
    private SpuMapper spuMapper;
    @Resource
    private BrandMapper brandMapper;
    @Resource
    private CategoryService categoryService;
    @Resource
    private SkuMapper skuMapper;
    @Resource
    private StockMapper stockMapper;

    @Resource
    private AmqpTemplate amqpTemplate;

    /**
     * 分页查询商品spu
     *
     * @param key
     * @param saleable
     * @param page
     * @param rows
     * @return
     */
    public PageResult<SpuBo> findSpuByPage(String key, Boolean saleable, Integer page, Integer rows) {

        //1.添加查询条件
        Example example = new Example(Spu.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(key)) {
            criteria.andLike("title", "%" + key + "%");
        }
        //2.添加上下架的过滤条件
        if (saleable != null) {
            criteria.andEqualTo("saleable", saleable);
        }
        //3.添加分页条件
        PageHelper.startPage(page, rows);//pageHelper分页工具
        //4.执行查询,获取spu
        List<Spu> spuList = spuMapper.selectByExample(example);
        //5.转化成SpuBo的集合
        List<SpuBo> spuBoList = spuList.stream().map(spu -> {
            SpuBo spuBo = new SpuBo();
            BeanUtils.copyProperties(spu, spuBo);//复制bean的属性
            //完善spuBo的属性,查询分类和品牌名
            spuBo.setBname(this.brandMapper.selectByPrimaryKey(spu.getBrandId()).getName());//品牌
            List<String> names = categoryService.findByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));
            spuBo.setCname(StringUtils.join(names, "-"));//分类名,以-分隔
            return spuBo;//返回值添加到新的集合中
        }).collect(Collectors.toList());
        //6.返回PageResult
        PageInfo<Spu> pageInfo = new PageInfo<Spu>(spuList);
        return new PageResult(pageInfo.getTotal(), spuBoList);
    }

    /**
     * 添加商品信息:spu,spuDetails,skus,stock
     *
     * @param spuBo
     * @return
     */
    @Transactional  //添加事务,出现问题回滚事务
    public Boolean saveGoods(SpuBo spuBo) {

        //1.先新增Spu,否则无法获取spuId
        //先将前台获取的spuId(防止前台模拟ID数据恶意注入)设置为空
        spuBo.setId(null);
        spuBo.setCreateTime(new Date());
        spuBo.setLastUpdateTime(spuBo.getCreateTime());
        spuBo.setSaleable(true);

        spuMapper.insertSelective(spuBo);
        //2.新增SpuDetails
        spuBo.getSpuDetail().setSpuId(spuBo.getId());
        spuDetailMapper.insertSelective(spuBo.getSpuDetail());
        //3.新增Sku:遍历新增
        saveSku(spuBo);
        //4.发送消息到消息队列,提示更新elasticsearch
        sendMsg("insert",spuBo.getId());

        return true;
    }

    /**
     * 向RabbitMQ发送消息
     * @param type
     * @param spuId
     */
    private void sendMsg(String type,Long spuId) {
        //发送消息到消息队列,提示更新elasticsearch
        try {
            this.amqpTemplate.convertAndSend("item."+type,spuId);
            //避免因为消息发送失败导致数据添加失败
        } catch (AmqpException e) {
            e.printStackTrace();
        }
    }

    /**
     * 新增sku,stock
     * @param spuBo
     */
    private void saveSku(SpuBo spuBo) {
        spuBo.getSkus().forEach(sku -> {
            sku.setId(null);
            sku.setCreateTime(new Date());
            sku.setLastUpdateTime(sku.getCreateTime());
            sku.setSpuId(spuBo.getId());
            skuMapper.insertSelective(sku);
            //4.新增Stock
            Stock stock = new Stock();
            stock.setStock(sku.getStock());
            stock.setSkuId(sku.getId());
            stockMapper.insertSelective(stock);
        });
    }

    /**
     * 更新商品信息
     *
     * @param spuBo
     * @return
     */
    public boolean updateGoods(SpuBo spuBo) {

        //1.操作Sku相关,查询要删除的sku
        Sku record = new Sku();
        record.setSpuId(spuBo.getId());
        List<Sku> oldSkus = skuMapper.select(record);
        //1.1 删除stock
        oldSkus.forEach(sku -> {
            stockMapper.deleteByPrimaryKey(sku.getId());
        });
        //1.2 删除sku
        skuMapper.delete(record);
        //1.3 新增Sku,Stock
        saveSku(spuBo);

        //2.操作spu相关
        spuMapper.updateByPrimaryKey(spuBo);
        spuDetailMapper.updateByPrimaryKey(spuBo.getSpuDetail());
        //3.发送消息
        sendMsg("update",spuBo.getId());
        return true;
    }

    /**
     * 根据spuId查询spu详情
     * @param spuId
     * @return
     */
    public SpuDetail findSpuDetailById(Long spuId) {
        return spuDetailMapper.selectByPrimaryKey(spuId);
    }

    /**
     * 根据SpuId查询sku集合
     *
     * @param spuId
     * @return
     */
    public List<Sku> findSkusBySpuId(Long spuId) {
        Sku example = new Sku();
        example.setSpuId(spuId);
        List<Sku> skuList = skuMapper.select(example);
        skuList.forEach(sku -> {
            sku.setStock(stockMapper.selectByPrimaryKey(sku.getId()).getStock());
        });
        return skuList;
    }
    /**
     * 根据id查询spu
     * @param spuId
     * @return
     */
    public Spu findSpuById(Long spuId) {
        return spuMapper.selectByPrimaryKey(spuId);
    }


    /**
     * 根据skuId查询sku
     * @param id
     * @return
     */
    public Sku querySkuById(Long id) {
        return this.skuMapper.selectByPrimaryKey(id);
    }

}
